package arehart.tyler;

import java.util.Timer;
import java.util.TimerTask;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;

public class BeepService extends IntentService {

	private int metersAway = 1000;
	private Location target;
	private Location phone;
	private boolean running = false;
	private SoundPool soundPool;
	private int soundId;
	private AudioManager mAudioManager;
	private boolean locationAvailable = true;
	private LocationManager locationManager;
	private LocationListener locationListener;
	public String distancetext;
	
	
	private final IBinder mBinder = new LocalBinder();

	/**
	 * A constructor is required, and must call the super IntentService(String)
	 * constructor with a name for the worker thread.
	 */
	public BeepService() {
		super("BeepService");
	}
	
	public class LocalBinder extends Binder {
        BeepService getService() {
            // Return this instance of LocalService so clients can call public methods
            return BeepService.this;
        }
    }

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {

		mAudioManager = (AudioManager) getBaseContext().getSystemService(
				Context.AUDIO_SERVICE);
		soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
		soundId = soundPool.load(getBaseContext(), R.raw.beep, 1);

		setupLocation();

		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

	/**
	 * The IntentService calls this method from the default worker thread with
	 * the intent that started the service. When this method returns,
	 * IntentService stops the service, as appropriate.
	 */
	@Override
	protected void onHandleIntent(Intent intent) {
		// Normally we would do some work here, like download a file.
		// For our sample, we just sleep for 5 seconds.
		long endTime = System.currentTimeMillis() + 5 * 1000;
		while (System.currentTimeMillis() < endTime) {
			synchronized (this) {
				try {
					wait(endTime - System.currentTimeMillis());
				} catch (Exception e) {
				}
			}
		}
	}
	
	

	private void beepSoon() {

		Timer t = new Timer();
		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				beep();
				if (running && locationAvailable) {
					beepSoon();
				}
			}
		};
		t.schedule(task, getBeepPeriod(metersAway));
	}

	private long getBeepPeriod(int meters) {
		return 200 + 100 * meters;

	}

	public void setTarget(View view) {
		target = phone;
	}



	private void setNewLocation(Location loc) {
		phone = loc;

		if (target != null) {
			float[] results = new float[1];
			Location.distanceBetween(phone.getLatitude(), phone.getLongitude(),
					target.getLatitude(), target.getLongitude(), results);
			metersAway = (int) results[0];

			distancetext = "" + metersAway;

			if (running) {
				if (metersAway < 2) {
					stop(null);
				}
			}
		} else {

			distancetext = "No target";
		}
	}
	
	public void start(View view) {
		running = true;
		beepSoon();
	}

	public void stop(View view) {
		running = false;
	}

	private void setupLocation() {
		// Acquire a reference to the system Location Manager
		locationManager = (LocationManager) this
				.getSystemService(Context.LOCATION_SERVICE);

		// Define a listener that responds to location updates
		locationListener = new LocationListener() {
			public void onLocationChanged(Location location) {

				if (location.getAccuracy() < 10)
					setNewLocation(location);
				else
					distancetext= location.getAccuracy() + "";
			}

			public void onStatusChanged(String provider, int status,
					Bundle extras) {
				switch (status) {
				case LocationProvider.OUT_OF_SERVICE:
				case LocationProvider.TEMPORARILY_UNAVAILABLE:
					locationAvailable = false;
					distancetext = "Location unavailable";
					break;
				case LocationProvider.AVAILABLE:
					locationAvailable = true;
					distancetext = "Location available";
				}

			}

			public void onProviderEnabled(String provider) {
			}

			public void onProviderDisabled(String provider) {
			}
		};

		requestUpdates();
	}

	private void requestUpdates() {

		// Register the listener with the Location Manager to receive location
		// updates
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				1000, 0, locationListener);

	}

	private void beep() {
		int streamVolume = mAudioManager
				.getStreamVolume(AudioManager.STREAM_MUSIC);
		soundPool.play(soundId, streamVolume, streamVolume, 1, 0, 1);
	}

	public void goLoud() {
		running = true;
		requestUpdates();
		
	}

	public void goQuiet() {
		running = false;
		locationManager.removeUpdates(locationListener);
	}
}